/*
 * @Description: Description
 * @Author: Kerwin
 * @Date: 2024-07-22 16:55:54
 * @LastEditTime: 2024-07-24 13:44:06
 * @LastEditors:  Please set LastEditors
 */
import { ComponentInternalInstance, CSSProperties } from 'vue'

export function createAnimation(options: any) {
  // #ifndef APP-NVUE
  return uni.createAnimation({ ...options })
  // #endif
}

/**
 * 将字符串转换为带有连字符分隔的小写形式
 * @param key - 要转换的字符串
 * @returns 转换后的字符串
 */
export function toLowercaseSeparator(key: string): string {
  return key.replace(/([A-Z])/g, '-$1').toLowerCase()
}

/**
 * 获取样式对象对应的样式字符串
 * @param style - CSS样式对象
 * @returns 由非空有效样式属性键值对组成的字符串
 */
export const sleep = (delay: number = 300) =>
  new Promise((resolve) => setTimeout(resolve, delay))

export function getStyleStr(style: CSSProperties): string {
  // #ifndef APP-IOS || APP-ANDROID
  return Object.keys(style)
    .filter(
      (key) =>
        style[key] !== undefined && style[key] !== null && style[key] !== ''
    )
    .map((key: string) => `${toLowercaseSeparator(key)}: ${style[key]};`)
    .join(' ')
  // #endif
}

/**
 * 检查一个值是否已定义（不为 undefined）且不为 null
 * @param value 要检查的值
 * @returns 如果值已定义且不为 null，则返回 true；否则返回 false
 */
// #ifndef UNI-APP-X
export function isDef(value: unknown): boolean {
  return value !== undefined && value !== null
}
// #endif

/**
 * 检查一个值是否为数字类型或表示数字的字符串
 * @param value 要检查的值，可以是 string 类型或 number 类型
 * @returns 如果值是数字类型或表示数字的字符串，则返回 true；否则返回 false
 */
export function isNumeric(value: string | number | undefined | null): boolean {
  return /^(-)?\d+(\.\d+)?$/.test(value)
}

/**
 * 给一个值添加单位（像素 px）
 * @param value 要添加单位的值，可以是字符串或数字
 * @returns 添加了单位的值，如果值为 null 则返回 null
 */

export function addUnit(value?: string | number): string | null {
  if (!isDef(value)) {
    return null
  }
  value = String(value) // 将值转换为字符串
  // 如果值是数字，则在后面添加单位 "px"，否则保持原始值
  return isNumeric(value) ? `${value}px` : value
}

/**
 * 获取节点信息
 * @param selector 选择器字符串
 * @param context ComponentInternalInstance 对象
 * @param node 是否获取node
 * @returns 包含节点信息的 Promise 对象
 */
export function getRect(
  selector: string,
  context: ComponentInternalInstance,
  node: boolean = false
) {
  // 之前是个对象，现在改成实例，防止旧版会报错
  if (context == null) {
    return Promise.reject('context is null')
  }
  if (context.context) {
    context = context.context
  }
  // #ifdef MP || VUE2
  if (context.proxy) context = context.proxy
  // #endif
  return new Promise<UniNamespace.NodeInfo>((resolve, reject) => {
    // #ifndef APP-NVUE
    const dom = uni.createSelectorQuery().in(context).select(selector)
    const result = (rect: UniNamespace.NodeInfo) => {

      if (rect) {
        resolve(rect)
      } else {
        reject('no rect')
      }
    }

    if (!node) {
      dom.boundingClientRect(result).exec()
    } else {
      dom
        .fields(
          {
            node: true,
            size: true,
            rect: true
          },
          result
        )
        .exec()
    }
    // #endif
    // #ifdef APP-NVUE
    let { context } = options
    if (/#|\./.test(selector) && context.refs) {
      selector = selector.replace(/#|\./, '')
      if (context.refs[selector]) {
        selector = context.refs[selector]
        if (Array.isArray(selector)) {
          selector = selector[0]
        }
      }
    }
    dom.getComponentRect(selector, (res) => {
      if (res.size) {
        resolve(res.size)
      } else {
        reject('no rect')
      }
    })
    // #endif
  })
}
